#pragma once

typedef int tMsgType;
typedef int tMsgTargetID;
const tMsgTargetID MSG_TARGET_ID_NONE = 0;
const tMsgTargetID MSG_TARGET_ID_ALL = -1;


struct sMsg
{
	sMsg() : msgType(0), 
		msgTargetID(MSG_TARGET_ID_NONE)
	{
	}

	virtual ~sMsg() {}

	virtual sMsg* Copy() = 0;

	tMsgType msgType;
	tMsgTargetID msgTargetID;
};

class iMsgTargetBase;

class iMsgManager
{
public:
	virtual tBool SendMsg(sMsg& msg) = 0;
	virtual tBool SendMsg(tMsgTargetID targetID, sMsg& msg) = 0;
	virtual tBool PostMsg(sMsg& msg, tFloat time) = 0;
	virtual tBool PostMsg(tMsgTargetID targetID, sMsg& msg, tFloat time) = 0;
	virtual tBool RegisterTarget(iMsgTargetBase* target) = 0;
	virtual tBool UnregisterTarget(iMsgTargetBase* target) = 0;
	virtual void Update(tFloat dt) = 0;
	virtual tSize CancelPostMsgTo(tMsgTargetID targetID) = 0;
};

class iMsgTargetBase
{
public:
	iMsgTargetBase() {}
	void SetMsgManager(iMsgManager* manager) { m_manager = manager; }
	virtual tMsgTargetID GetMsgTargetID() const = 0;
	virtual tBool _ON_MSG(sMsg&) { return false; }
	iMsgManager& GetMsgManager() { assert(m_manager); return *m_manager; }
private:
	iMsgManager* m_manager;
};

#define DECLARE_MSG_MAP \
	protected: \
	virtual bool _ON_MSG(sMsg& info);

#define BEGIN_MSG_MAP(THE_CLASS, BASE_CLASS) \
	bool THE_CLASS::_ON_MSG(sMsg& info) \
{ \
	typedef THE_CLASS	THE_CLASS_DEF; \
	typedef BASE_CLASS	BASE_CLASS_DEF; \
	switch (info.msgType) \
{

#define END_MSG_MAP() \
	case INT_MAX: \
	default: \
	break; \
} \
	return BASE_CLASS_DEF::_ON_MSG(info); \
}

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
#define MSG_MAP(NAMESPACE, TYPE, FUNC) \
			case NAMESPACE::eMSG::TYPE: \
			FUNC((NAMESPACE::s##TYPE&)info); \
			return true;
#else
#define MSG_MAP(NAMESPACE, TYPE, FUNC) \
			case NAMESPACE##::eMSG::##TYPE##: \
			FUNC##((NAMESPACE##::s##TYPE##&)info); \
			return true;
#endif
